package com.bestcem.xm.award.grpc.client;

import com.bestcem.bp.grpc.v1.base.Code;
import com.bestcem.bp.pay.grpc.v1.common.FinanceArgs;
import com.bestcem.bp.pay.grpc.v1.services.*;
import com.bestcem.xm.award.constant.Constants;
import com.bestcem.xm.award.enums.AwardStatusEnum;
import com.bestcem.xm.award.service.dto.ChangeActivityStatusBodyDTO;
import com.bestcem.xm.award.service.dto.pay.SendRedPacketResponse;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.common.core.domain.web.RpcStatusResult;
import com.bestcem.xm.common.core.grpcplatform.entity.GrpcPlatformDO;
import com.bestcem.xm.common.core.sign.grpc.core.GrpcTemplate;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * 钱包活动 grpc客户端
 *
 * @author sh.pei <sh.pei@idiaoyan.com>
 * @version v1.0
 * @date 2021/7/14 11:45
 */
@Service
@Slf4j
public class ActivityGrpcService {

    @GrpcClient(GrpcClientNames.PAY)
    private ActivityServiceGrpc.ActivityServiceBlockingStub activityServiceStub;

    @Resource
    private GrpcTemplate grpcTemplate;

    /**
     * 根据id查询钱包活动
     *
     * @param id 活动id
     * @return 查询结果
     */
    public GetActivityResponse getActivity(String id) {
        try {
            GetActivityRequest.Builder builder = GetActivityRequest.newBuilder();
            builder.setId(id);
            GetActivityRequest request = builder.build();
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.getActivity(request);
        } catch (Exception e) {
            log.error("[award] pay getActivity {} Error; ErrorMsg: {};", id, e.getMessage(), e);
            return GetActivityResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 创建钱包活动
     *
     * @param request 创建活动参数
     * @return 创建结果
     */
    public CreateActivityResponse createActivity(CreateActivityRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.createActivity(request);
        } catch (Exception e) {
            log.error("[award] pay createActivity {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return CreateActivityResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 删除钱包活动
     *
     * @param request 删除钱包活动请求参数
     * @return 删除钱包活动结果
     */
    public DeleteActivityResponse deleteActivity(DeleteActivityRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.deleteActivity(request);
        } catch (Exception e) {
            log.error("[award] pay deleteActivity {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return DeleteActivityResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 激活钱包活动
     *
     * @param request 激活钱包活动请求参数
     * @return 激活钱包活动结果
     */
    public ActivateActivityResponse activateActivity(ActivateActivityRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.activateActivity(request);
        } catch (Exception e) {
            log.error("[award] pay activateActivity {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return ActivateActivityResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 获取活动余额
     *
     * @param request 获取活动余额请求参数
     * @return 获取活动余额结果
     */
    public GetActivityRemainResponse getActivityRemain(GetActivityRemainRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.getActivityRemain(request);
        } catch (Exception e) {
            log.error("[award] pay getActivityRemain {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return GetActivityRemainResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 结束活动
     *
     * @param request 结束活动请求参数
     * @return 结束活动结果
     */
    public FinishActivityResponse finishActivity(FinishActivityRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            FinishActivityResponse finishActivityResponse = activityServiceStub.finishActivity(request);
            if (Code.OK_VALUE != finishActivityResponse.getStatus().getCodeValue()) {
                log.error("[award] pay finishActivity {} fail;  {};", request, finishActivityResponse.getStatus().getMessage());
            }
            return finishActivityResponse;
        } catch (Exception e) {
            log.error("[award] pay finishActivity {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return FinishActivityResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 暂停活动
     *
     * @param request 暂停活动请求参数
     * @return 暂停活动结果
     */
    public PauseActivityResponse pauseActivity(PauseActivityRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.pauseActivity(request);
        } catch (Exception e) {
            log.error("[award] pay pauseActivity {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return PauseActivityResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 继续活动
     *
     * @param request 继续活动请求参数
     * @return 继续活动结果
     */
    public ResumeActivityResponse resumeActivity(ResumeActivityRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.resumeActivity(request);
        } catch (Exception e) {
            log.error("[award] pay resumeActivity {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return ResumeActivityResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 领取红包
     * 钱包领取红包中的金额在普通红包、随机红包中没有使用，指定金额中有用。目前红包是没有指定金额的。所以参数中的amount的可以直接传0或者不传
     *
     * @param request 领取红包请求参数
     * @return 领取红包结果
     */
    public PickMoneyResponse pickMoney(PickMoneyRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.pickMoney(request);
        } catch (Exception e) {
            log.error("[award] pay pickMoney {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return PickMoneyResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 领取红包
     *
     * @param activityId 活动Id
     * @param orderId    seq id
     * @param openId     微信openId
     * @param basicName  名称
     * @param amount     金额，红包中固定传0
     * @return SendRedPacketResponse
     */
    public SendRedPacketResponse pickMoney(String activityId, String orderId, String openId, String basicName, int amount) {
        PickMoneyRequest.Builder builder = PickMoneyRequest.newBuilder();
        builder.setId(activityId);
        //不传或者填0
        builder.setAmount(amount);
        builder.setDesc(basicName);
        builder.setOpenId(openId);
        builder.setOrderId(orderId);

        GrpcPlatformDO serverTemplate = grpcTemplate.getServerTemplate(GrpcTemplate.SEVER_CODE_PAY);
        if (serverTemplate != null) {
            builder.setPlatformCode(serverTemplate.getPCode());
        } else {
            log.error("pay pcode 没有配置!");
            return null;
        }


        PickMoneyResponse pickMoneyResponse = pickMoney(builder.build());

        //失败返回Null
        if (pickMoneyResponse == null || pickMoneyResponse.getStatus().getCode().getNumber() != Code.OK.getNumber()) {
            log.error("pickMoney error activityId:{},openid:{},code:{},msg:{}", activityId, openId, pickMoneyResponse != null ? pickMoneyResponse.getStatus().getCodeValue() : 0, pickMoneyResponse != null ? pickMoneyResponse.getStatus().getMessage() : null);
            return null;
        }
        PickMoneyInfo pickMoneyInfo = pickMoneyResponse.getPickMoney();
        SendRedPacketResponse sendRedPacketResponse = new SendRedPacketResponse();
        sendRedPacketResponse.setStatus(pickMoneyInfo.getStatus().getNumber());
        //单位分
        sendRedPacketResponse.setAmount(pickMoneyInfo.getAmount());

        return sendRedPacketResponse;
    }


    /**
     * 获取红包领取状态
     *
     * @param request 获取红包领取状态请求参数
     * @return 获取红包领取状态结果
     */
    public GetLuckyMoneyStatusResponse getLuckyMoneyStatus(GetLuckyMoneyStatusRequest request) {
        try {
            grpcTemplate.addSign(request, GrpcTemplate.SEVER_CODE_PAY);
            return activityServiceStub.getLuckyMoneyStatus(request);
        } catch (Exception e) {
            log.error("[award] pay getLuckyMoneyStatus {} Error; ErrorMsg: {};", request, e.getMessage(), e);
            return GetLuckyMoneyStatusResponse.newBuilder().setStatus(RpcStatusResult.error("钱包服务调用失败")).build();
        }
    }

    /**
     * 调用钱包中心 更改活动状态
     *
     * @param activityId    活动id
     * @param status        需要更改的奖励状态
     * @param currentStatus 当前奖励状态
     * @param bodyDTO       请求体
     * @return 请求是否成功
     */
    public boolean changeActivityStatus(String activityId, Integer status, Integer currentStatus, ChangeActivityStatusBodyDTO bodyDTO) {
        boolean result;
        if (status == AwardStatusEnum.ACTIVE.getIndex()) {
            if (currentStatus == AwardStatusEnum.INACTIVE.getIndex()) {
                // 未激活 -> 激活  激活活动
                ActivateActivityRequest request = paramToActivateActivityRequest(activityId, bodyDTO);
                ActivateActivityResponse response = activateActivity(request);
                result = response.getStatus().getCodeValue() == Code.OK_VALUE
                        && StringUtils.isNotBlank(response.getFinanceInfo().getId());
            } else {
                // 其他状态 -> 激活  恢复活动
                ResumeActivityRequest request = paramToResumeActivityRequest(activityId);
                ResumeActivityResponse response = resumeActivity(request);
                result = response.getStatus().getCodeValue() == Code.OK_VALUE
                        && StringUtils.isNotBlank(response.getId());
            }
        } else if (status == AwardStatusEnum.FINISH.getIndex()) {
            // 任意状态 -> 结束  结束活动
            FinishActivityRequest request = this.paramToFinishActivityRequest(activityId, bodyDTO);
            FinishActivityResponse response = finishActivity(request);
            result = response.getStatus().getCodeValue() == Code.OK_VALUE
                    && StringUtils.isNotBlank(response.getId());
        } else if (status == AwardStatusEnum.PAUSE.getIndex()) {
            // 任意状态 -> 暂停  暂停活动
            PauseActivityRequest request = paramToPauseActivityRequest(activityId);
            PauseActivityResponse response = pauseActivity(request);
            result = response.getStatus().getCodeValue() == Code.OK_VALUE
                    && StringUtils.isNotBlank(response.getId());
        } else {
            result = false;
        }
        return result;
    }

    /**
     * 参数转换 激活活动请求
     *
     * @param activityId 活动id
     * @param bodyDTO    请求体
     * @return 激活活动请求
     */
    private ActivateActivityRequest paramToActivateActivityRequest(String activityId, ChangeActivityStatusBodyDTO bodyDTO) {
        FinanceArgs financeArgs = this.bodyToFinanceArgs(bodyDTO);
        ActivateActivityRequest.Builder builder = ActivateActivityRequest.newBuilder();
        builder.setId(activityId);
        builder.setFinanceArgs(financeArgs);
        return builder.build();
    }

    /**
     * 参数转换 恢复活动请求
     *
     * @param activityId 活动id
     * @return 恢复活动请求
     */
    private ResumeActivityRequest paramToResumeActivityRequest(String activityId) {
        ResumeActivityRequest.Builder builder = ResumeActivityRequest.newBuilder();
        builder.setId(activityId);
        return builder.build();
    }

    /**
     * 参数转换 结束活动请求
     *
     * @param activityId 活动id
     * @param bodyDTO    请求体
     * @return 结束活动请求
     */
    private FinishActivityRequest paramToFinishActivityRequest(String activityId, ChangeActivityStatusBodyDTO bodyDTO) {
        FinanceArgs financeArgs = this.bodyToFinanceArgs(bodyDTO);
        FinishActivityRequest.Builder builder = FinishActivityRequest.newBuilder();
        builder.setId(activityId);
        builder.setFinanceArgs(financeArgs);
        return builder.build();
    }

    /**
     * 参数转换 暂停活动请求
     *
     * @param activityId 活动id
     * @return 暂停活动请求
     */
    private PauseActivityRequest paramToPauseActivityRequest(String activityId) {
        PauseActivityRequest.Builder builder = PauseActivityRequest.newBuilder();
        builder.setId(activityId);
        return builder.build();
    }

    /**
     * 参数转换
     *
     * @param bodyDTO 参数
     * @return FinanceArgs
     */
    private FinanceArgs bodyToFinanceArgs(ChangeActivityStatusBodyDTO bodyDTO) {
        FinanceArgs.Builder builder = FinanceArgs.newBuilder();
        builder.setOpUserId(bodyDTO.getOpUserId());
        builder.setOpUserName(bodyDTO.getOpUserName());
        builder.setRemark(bodyDTO.getRemark());
        return builder.build();
    }

    /**
     * 生成remark
     *
     * @param projectTitle  项目名称
     * @param awardTypeName 奖励类型名称
     * @param awardName     奖励名称
     * @return remark 最长长度255
     */
    public String genRemark(String projectTitle, String awardTypeName, String awardName) {
        StringBuilder result = new StringBuilder();
        result.append(projectTitle).append(Constants.HYPHEN).append(awardTypeName);
        if (StringUtils.isNotBlank(awardName)) {
            result.append(Constants.HYPHEN).append(awardName);
        }
        return result.length() > Constants.REMARK_MAX
                ? result.substring(Constants.ZERO, Constants.REMARK_MAX)
                : result.toString();
    }

}
